﻿using Autofac;
using Autofac.Integration.Mef;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Reflection;

namespace TestMef
{
    public static class Mef
    {
        #region 属性  
        public static IContainer Current { get; set; }
        private static readonly string AppExecuteRootDir;//程序执行主目录，对于网站就是BIN。
        public static HashSet<string> ExportedDlls;


        #endregion

        #region 构造

        /// <summary>
        /// 静态构造函数
        /// </summary>
        static Mef()
        {
            AppExecuteRootDir = AppDomain.CurrentDomain.BaseDirectory;
            ExportedDlls = new HashSet<string>();
        }

        #endregion

        /// <summary>
        /// 完成初始化只能build一次 所以将这个状态设置放出来供业务判断是否需要再此之前进行服务注入
        /// </summary>
        public static IContainer Compelted(this ContainerBuilder builder)
        {
            Current = builder.Build();
            return Current;
        }

        public static ContainerBuilder AddMefContainer(this ContainerBuilder builder)
        {
            var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly()); 
            builder.RegisterComposablePartCatalog(catalog);
            builder.RegisterType<LogHelper2>().AsSelf().SingleInstance().PropertiesAutowired(new AutowiredPropertySelector());
            //builder.RegisterGeneric(typeof(Logger<>)).As(typeof(ILogger<>)).SingleInstance();
            // // 注册 ILogger<T>，使用 Microsoft.Extensions.Logging 中的实现
            // builder.RegisterGeneric(typeof(Logger<>)).As(typeof(ILogger<>)).SingleInstance().PropertiesAutowired(new AutowiredPropertySelector()); //允许属性注入

            // // 注册 TestMefExport 类
            //// builder.RegisterType<TestMefExport>();
            return builder;
        }

        #region 初始化     

        public static ContainerBuilder AddByFilterPattern(this ContainerBuilder builder, string assemblyFilterPattern)
        {
            AddByFilterPattern(assemblyFilterPattern);
            return builder;
        }

        public static ContainerBuilder AddByDir(this ContainerBuilder builder, string relativePath)
        {
            AddByDir(relativePath);
            return builder;
        }



        /// <summary>
        /// 在运行根目录搜索符合表达式的DLL
        /// </summary>
        /// <param name="relativePath">程序集筛选表达式，如"*.ClientProxy.dll"</param>
        public static void AddByDir(string relativePath)
        {
            string directory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, relativePath);
            if (!Directory.Exists(directory))
            {
                LogHelper.Error($"扫描dll目录[{directory}]不存在");
                return;
            }
            //var dllPaths = Directory.GetFiles(directory, "*.*", SearchOption.AllDirectories).Where(x => x.ToLower().EndsWith("*.dll"));
            var dllPaths = Directory.GetFiles(directory, "*.dll", SearchOption.AllDirectories);//.Where(x => x.ToLower().EndsWith("*.dll"));
            foreach (var dllPath in dllPaths)
            {
                ExportedDlls.Add(dllPath);
            }
        }

        public static void ExceptDll(string relativePath)
        {
            string dll = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, relativePath);
            ExportedDlls.Remove(dll);
        }


        /// <summary>
        /// 在运行根目录搜索符合表达式的DLL
        /// </summary>
        /// <param name="assemblyFilterPattern">程序集筛选表达式，如"*.ClientProxy.dll"</param>
        public static void AddByFilterPattern(string assemblyFilterPattern)
        {
            AddByFilterPattern(new List<string>() { assemblyFilterPattern });
        }

        /// <summary>
        /// 在运行根目录搜索符合表达式的DLL
        /// </summary>
        /// <param name="assemblyFilterPatterns">程序集筛选表达式，如"*.ClientProxy.dll"</param>
        public static void AddByFilterPattern(List<string> assemblyFilterPatterns)
        {
            if (assemblyFilterPatterns != null)
            {
                //扫描所有程序集，反射注册命令
                var exeDir = new DirectoryInfo(AppExecuteRootDir);

                assemblyFilterPatterns.ForEach(s =>
                {
                    //搜索根目录
                    FileInfo[] executorDlls = exeDir.GetFiles(s);

                    //处理目录下程序集
                    if (executorDlls.Length > 0)
                    {
                        executorDlls.ToList().ForEach(
                            dll =>
                            {
                                ExportedDlls.Add(dll.FullName);
                            }
                        );
                    }
                });
            }
        }

        #endregion




        #region 获取实例    


        public static T GetService<T>()
        {
            return Current.Resolve<T>();
        }
        /// <summary>
        /// 注意释放
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public static T GetService<T>(string key)
        {
            return Current.ResolveKeyed<T>(key);
        }


        public static IEnumerable<T> GetServices<T>()
        {
            return Current.Resolve<IEnumerable<T>>();
        }

        public static IEnumerable<T> GetServices<T>(string key)
        {
            return Current.ResolveKeyed<IEnumerable<T>>(key);
        }

        /// <summary>
        /// 注意释放
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static object GetService(Type type)
        {
            return Current.Resolve(type);
        }

        public static object GetService(string key, Type type)
        {
            return Current.ResolveKeyed(key, type);
        }
        /// <summary>
        /// 获取LifeTimeScope
        /// </summary>
        /// <returns></returns>
        public static ILifetimeScope GetLifeTimeScope()
        {
            return Current.BeginLifetimeScope();
        }

        /// <summary>
        ///是否注册
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static bool IsRegistered<T>()
        {
            return Current.IsRegistered<T>();
        }

        /// <summary>
        /// 注册
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public static bool IsRegistered<T>(string key)
        {
            return Current.IsRegisteredWithKey<T>(key);
        }

        public static bool IsRegistered(Type type)
        {
            return Current.IsRegistered(type);
        }

        public static bool IsRegisteredWithKey(string key, Type type)
        {
            return Current.IsRegisteredWithKey(key, type);
        }



        #endregion
    }
}
